
package com.wwy.monitor.service;

import com.alibaba.fastjson.JSON;
import com.wwy.monitor.common.MessageException;
import com.wwy.monitor.model.enumeration.DeleteEnum;
import com.wwy.monitor.model.enumeration.EnableStatusEnum;
import com.wwy.monitor.model.enumeration.MailTemplateEnum;
import com.wwy.monitor.model.tddl.dto.MonitorAppDTO;
import com.wwy.monitor.model.tddl.dto.MonitorConfigDetailDTO;
import com.wwy.monitor.model.tddl.dto.MonitorIpDTO;
import com.wwy.monitor.model.tddl.query.MonitorIpQuery;
import com.wwy.monitor.model.vo.CaseVO;
import com.wwy.monitor.model.vo.SimpleCaseVO;
import com.wwy.monitor.util.OkHttpUtil;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author tianquan.ld
 * @version V1.0
 * <p>Description: case service</p>
 * @date 2019-11-01 17:30
 */
@Service(value = "caseService")
public class CaseService {
    private final static Logger logger = LoggerFactory.getLogger(CaseService.class);
    @Resource(name = "monitorAppService")
    private MonitorAppService monitorAppService;
    @Resource(name = "monitorIpService")
    private MonitorIpService monitorIpService;
    @Resource(name = "monitorMailService")
    private MonitorMailService monitorMailService;
    @Resource(name = "monitorConfigDetailService")
    private MonitorConfigDetailService monitorConfigDetailService;
    @Value("${server.port}")
    private Integer port;
    @Value("${system.server.protocol}")
    private String protocol;

    /**
     * 校验caseå¹¶åéé®ä»¶
     *
     * @param emailAddress é®ä»¶å°å
     * @param caseVO       caseå®ä½
     */
    public void handleCase(String emailAddress, CaseVO caseVO) {
        try {
// 校验
            MonitorAppDTO monitorApp = monitorAppService.selectById(caseVO.getAppId());
            if (monitorApp == null) {
                logger.info("æªåç°å¯ç¨åºç¨ï¼caseï¼" + JSON.toJSONString(caseVO));
                return;
            }
            MonitorIpQuery query = new MonitorIpQuery();
            query.setAppId(caseVO.getAppId());
            query.setStatus(EnableStatusEnum.ENABLE.getValue());
            query.setIsDelete(DeleteEnum.NOT_DELETE.getValue());
            List<MonitorIpDTO> ipList = monitorIpService.selectByQuery(query);
            if (CollectionUtils.isEmpty(ipList)) {
                logger.info("åºç¨æ å¯ç¨ipï¼caseï¼" + JSON.toJSONString(caseVO));
                return;
            }
// è¯·æ±åºç¨
            Map<String, String> ipMap = execute(caseVO, ipList);
            if (MapUtils.isEmpty(ipMap)) {
                logger.info("æªè·åååºï¼caseï¼" + JSON.toJSONString(caseVO));
                return;
            }
            Map<String, Object> templateMap = new HashMap<>();
            MailTemplateEnum mailTemplateEnum = null;
// ææå¼ä¸ä¸ºç©ºï¼åä¸ææå¼åå¯¹æ¯
            if (StringUtils.isNotBlank(caseVO.getExcept())) {
                List<String> consistentIpList = ipMap.entrySet().stream()
                        .filter((item) -> caseVO.getExcept().equals(item.getValue()))
                        .map((item) -> item.getKey())
                        .collect(Collectors.toList());
                List<String> inConsistentIpList = ipMap.entrySet().stream()
                        .filter((item) -> !caseVO.getExcept().equals(item.getValue()))
                        .map((item) -> item.getKey())
                        .collect(Collectors.toList());
                templateMap.put("consistentIpList", consistentIpList);
                templateMap.put("inConsistentIpList", inConsistentIpList);
                templateMap.put("except", caseVO.getExcept());
                mailTemplateEnum = MailTemplateEnum.CASE_WITH_EXCEPT;
            } else {
// ææå¼ä¸ºç©ºï¼åæ ¹æ®ç»æåç»
                Map<String, List<String>> resultMap = new HashMap<>();
                ipMap.entrySet().stream().forEach((item) -> {
                    List<String> innerIpList = resultMap.get(item.getValue());
                    if (CollectionUtils.isEmpty(innerIpList)) {
                        innerIpList = new ArrayList<>();
                        innerIpList.add(item.getKey());
                        resultMap.put(item.getValue(), innerIpList);
                    } else {
                        innerIpList.add(item.getKey());
                    }
                });
                mailTemplateEnum = MailTemplateEnum.CASE_WITHOUT_EXCEPT;
                templateMap.put("resultMap", resultMap);
            }
            if (mailTemplateEnum == null) {
                throw new MessageException("caseéªè¯ï¼æªæ¾å°é®ä»¶æ¨¡æ¿");
            }
// åéé®ä»¶
            monitorMailService.sendMail("system", emailAddress, mailTemplateEnum.getTitle()
                    , mailTemplateEnum.getTemplateName(), templateMap, true);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    /**
     * éåè¯·æ±æºå¨
     *
     * @param caseVO
     * @param ipList
     * @return
     */
    private Map<String, String> execute(CaseVO caseVO, List<MonitorIpDTO> ipList) {
        Map<String, String> result = new HashMap<>();
        if (CollectionUtils.isEmpty(ipList)) {
            return result;
        }
        ipList.stream().forEach((item) -> {
            String host = protocol + item.getIp();
            try {
                String response = OkHttpUtil.submitForString(host, port, caseVO.getUrl()
                        , caseVO.getRequestMethod(), caseVO.getRequestHeader(), caseVO.getParam(), false, caseVO.getContentType());
                result.put(item.getIp(), response);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
                result.put(item.getIp(), e.getMessage());
            }
        });
        return result;
    }

    /**
     * åæºå¨caseéªè¯
     *
     * @param simpleCaseVO
     * @return
     */
    public String simpleCase(SimpleCaseVO simpleCaseVO) {
// 校验
        MonitorAppDTO monitorApp = monitorAppService.selectById(simpleCaseVO.getAppId());
        if (monitorApp == null) {
            throw new MessageException("è¯¥åºç¨ä¸å­å¨");
        }
        MonitorIpDTO ipDTO = monitorIpService.selectById(simpleCaseVO.getIpId());
        if (null == ipDTO || !ipDTO.getAppId().equals(monitorApp.getId())) {
            throw new MessageException("ipIdéè¯¯!");
        }
        MonitorConfigDetailDTO detailDTO = monitorConfigDetailService.selectById(simpleCaseVO.getDetailId());
        if (null == detailDTO) {
            throw new MessageException("éç½®ä¸å­å¨!");
        }
        CaseVO caseVO = new CaseVO();
        caseVO.setAppId(ipDTO.getAppId());
        caseVO.setExcept(detailDTO.getExcept());
        caseVO.setParam(detailDTO.getParam());
        caseVO.setRequestHeader(detailDTO.getRequestHeader());
        caseVO.setRequestMethod(detailDTO.getRequestMethod());
        caseVO.setUrl(detailDTO.getUrl());
        caseVO.setContentType(detailDTO.getContentType());
        List<MonitorIpDTO> ipList = Lists.newArrayList();
        try {
            ipList.add(ipDTO);
            Map<String, String> ipMap = execute(caseVO, ipList);
            if (MapUtils.isEmpty(ipMap)) {
                logger.info("æªè·åååºï¼caseï¼" + JSON.toJSONString(simpleCaseVO));
                return "æªè·åååº";
            }
            return ipMap.get(ipDTO.getIp());
        } catch (Exception e) {
            e.printStackTrace();
            return "è·åååºå¼å¸¸";
        }
    }
}